/**
 * @class UI层级管理
 * @author DuskyHuang 圣子
 * @description 为UI体统层级管理。
*/

import { _decorator, Node, Animation, Prefab, instantiate } from 'cc';
import { Mediator, TweenSwitcher, utils } from 'cfw';
import { UI, } from 'notifications';
const { ccclass, property } = _decorator;
const { group, setBottom, setTop } = utils;

function useGB(this: LayersMediator): boolean { return this.useGB; }

@ccclass('cocosmos.layers-mediator')
export class LayersMediator extends Mediator {

    @property(Node) public screenMask: Node = null;

    @group('Base', '', Node) public baseLayer: Node = null;
    @group('Base', '', [Prefab]) public baseTemplates: Prefab[] = [];

    @group('Panel', '', Node) public panelLayer: Node = null;
    @group('Panel', '', [Prefab]) public panelTemplates: Prefab[] = [];
    @group('Panel', '启用自动回收') public useGB: boolean = true;
    @group('Panel', '', useGB, [0, 100, 0.1]) public intervalGB: time.sec = 5;
    @group('Panel', '', [Prefab], useGB) public largePanels: Prefab[] = [];

    @group('Popup', '', Node) public popupLayer: Node = null;
    @group('Popup', '', [Prefab]) public popupTemplates: Prefab[] = [];


    protected onLoad(): void {
        this._init();
        this._listen();
    }

    protected _init(): void {
        this.baseTemplates.forEach(base => this.baseLayer.addChild(instantiate(base)));
        this.popupTemplates.forEach(popup => this.popupLayer.addChild(instantiate(popup)));
    }

    private _listen(): void {
        this.on(UI.Panels.OPEN, this.onOpenPanel);
        this.on(UI.Panels.CLOSE, this.onClosePanel);
        this.on(UI.FULL_SCREEN, this.onFullscreen);
    }

    protected onOpenPanel(name: string, layer?: 'top' | 'bottom'): void {
        let panel = this._panels.find(pnl => pnl.name === name);
        if (!panel) {
            const template = this.panelTemplates.find(tmp => tmp.name === name);
            if (!template) return console.warn("[layers-mediator]", "template not exist for:", name);
            panel = instantiate(template);
            this._panels.push(panel);
        }
        if (panel.activeInHierarchy) return;
        panel.parent = this.panelLayer;
        if (layer === 'bottom') setBottom(panel);
        const anim = panel.getComponent(Animation);
        const show = anim?.clips.find(clip => clip.name.includes('show'));
        anim && show && anim.play(show.name);
    }

    protected onClosePanel(name: string): void {
        const panel = this.panelLayer.getChildByName(name);
        if (!panel) return;
        const anim = panel.getComponent(Animation);
        const hide = anim?.clips.find(c => c.name.includes('hide'));
        if (anim && hide) anim.play(hide.name);
        else panel.removeFromParent();

    }

    protected onFullscreen(isFull: boolean): void {
        this.screenMask.active = !isFull;
        this.baseLayer.children.forEach(child =>
            child.children.forEach(grandchild =>
                grandchild.getComponent(TweenSwitcher)?.play(!isFull, true)));
    }

    private _tryGarbageCollection(): void {
        if (this._panels.length <= 0) return;
        const garbageNames = this.largePanels.map(tmp => tmp.name);
        for (let panel of this._panels) {
            // 大预制体，每隔一段时间不在场景中就会被销毁，每次垃圾回收销毁一个
            if (garbageNames.contains(panel.name) && !panel.activeInHierarchy) {
                this._panels.remove(panel);
                panel.destroy();
                return;
            }
        }
    }

    protected start(): void {
        if (this.useGB) {
            this.schedule(() => {
                this._tryGarbageCollection();
            }, this.intervalGB);
        }
    }

    private _panels: Node[] = [];
    private _popups: Node[] = [];
}